# encoding: utf-8
"""
Databases Modules
=======

Modules enable logical resource separation.

You may control enabled modules by modifying ``ENABLED_MODULES`` config
variable.
"""
import logging, time, datetime
from app.modules.common.utils import path_modify_time
from app.extensions import db, log
from app.extensions.api import api_v1
from app.modules.apps.models import App
from app.modules.common.pipelines import PipelineStatusListner, PipelineOnStartedEvent, PipelineOnDoneEvent, \
    PipelineOnFailedEvent, PipelineProgressChangedEvent
from app.modules.database.pipelines_factory import DatabasePipelinesFactory


# log = logging.getLogger(__name__)


def init_app(app, **kwargs):
    """
    Init database module.
    """
    from . import models, resources

    api_v1.add_namespace(resources.api)

    from .pipelines_factory import DatabasePipelinesFactory
    from .pipelines_mysql import ImportMysqlPipeLine
    from .pipelines_oracle import InitImportOraclePipeLine, IncrementalImportOraclePipeLine
    from .pipelines_cassandra import InitImportCassandraPipeLine
    from ..common import pipeline_manager
    from app.modules.apps.models import App

    with app.app_context():
        container_pipeline_listner = ContainerDbPipelineListner(app)
        pipeline_manager.subscribe(container_pipeline_listner)

        apps = App.query.filter_by(disabled = 0).order_by(App.starting_order.asc()).all()
        pipeline_manager.register_pipeline_factory(DatabasePipelinesFactory(apps))


class ContainerDbPipelineListner(PipelineStatusListner):
    def __init__(self, app):
        super(ContainerDbPipelineListner, self).__init__()
        self._app = app

    def on_event(self, event):

        _pipeline_name = str(event.pipeline.name)

        if _pipeline_name.startswith('pip-db:'):

            zone_alias = None
            db_type, db_name, data_from = DatabasePipelinesFactory.resolve_pipeline_name(_pipeline_name)

            if isinstance(event, PipelineOnStartedEvent):
                self.update_db_import_date(zone_alias, db_type, db_name)
                params = event.pipeline.params()
                if 'dump_path' in params.keys():
                    dump_path = params['dump_path']
                    m_time = path_modify_time(dump_path)
                    if m_time:
                        db_dump_create_date = time.strftime('%Y%m%d-%H%M%S', m_time)
                        self.update_db_dump_create_date(zone_alias, db_type, db_name, db_dump_create_date)

                change_status = 'running'

            elif isinstance(event, PipelineOnDoneEvent):
                change_status = 'ready'

            elif isinstance(event, PipelineOnFailedEvent):
                log.error("%s 发生异常 异常信息:%s" % (_pipeline_name, event.err_msg))
                print("%s 发生异常 异常信息:%s" % (_pipeline_name, event.err_msg))
                change_status = 'unavailable'

            elif isinstance(event, PipelineProgressChangedEvent):
                change_status = None

            else:
                change_status = None

            self.update_db_status(zone_alias, db_type, db_name, change_status)

    def update_db_status(self, zone_alias, db_type, db_name, change_status):

        if change_status:
            with self._app.app_context():
                try:
                    apps = App.query.filter_by(disabled = 0).filter_by(db_type = db_type).filter_by(
                        db_name = db_name).order_by(App.starting_order.asc()).all()

                    for app in apps:
                        app.db_status = change_status
                    db.session.commit()
                except Exception, e:
                    log.error(u'更新数据库导入状态【%s %s %s】失败，失败原因：%s', db_type, db_name, change_status, e.message)

    def update_db_dump_create_date(self, zone_alias, db_type, db_name, db_dump_create_date):

        if db_dump_create_date:
            with self._app.app_context():
                try:
                    apps = App.query.filter_by(disabled = 0).filter_by(db_type = db_type).filter_by(
                        db_name = db_name).order_by(App.starting_order.asc()).all()

                    for app in apps:
                        app.db_dump_create_date = db_dump_create_date
                    db.session.commit()
                except Exception, e:
                    log.error(u'更新数据库dump文件创建时间失败【%s %s】，失败原因：%s', db_type, db_name, e.message)

    def update_db_import_date(self, zone_alias, db_type, db_name):

        with self._app.app_context():
            try:
                apps = App.query.filter_by(disabled = 0).filter_by(db_type = db_type).filter_by(
                    db_name = db_name).order_by(App.starting_order.asc()).all()

                for app in apps:
                    app.db_import_date = datetime.datetime.now()
                db.session.commit()
            except Exception, e:
                log.error(u'更新数据库导入时间失败【%s %s】，失败原因：%s', db_type, db_name, e.message)
